import { onMounted, onUnmounted, shallowRef, toValue, ref, toRef } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
import { gsap } from 'gsap'
import { useWindowSize, watchThrottled, useEventListener } from '@vueuse/core'

export const useWindowResize = (func: (viewPortWidth: number) => void, delay: number = 100) => {
  const { width } = useWindowSize()

  onMounted(() => {
    func?.(width.value)
  })

  watchThrottled(
    () => width.value,
    (w: number) => {
      func?.(w)
    },
    { throttle: delay },
  )
}

export const useGsapContext = (fn: () => void) => {
  const gsapCtx = shallowRef<gsap.Context | null>(null)

  onMounted(() => (gsapCtx.value = gsap.context(fn)))
  onUnmounted(() => gsapCtx.value?.revert())

  return {
    gsapCtx,
  }
}

export const useDragScroll = (
  target: MaybeRefOrGetter<HTMLElement | null>,
): {
  enable: () => void
  disable: () => void
} => {
  const containerRef = toRef(() => toValue(target))
  const isDragging = ref(false)
  const startX = ref(0)
  const startScrollLeft = ref(0)

  const stopListeners = ref<(() => void)[]>([])

  const handleMouseDown = (e: MouseEvent) => {
    isDragging.value = true
    startX.value = e.clientX
    startScrollLeft.value = containerRef.value?.scrollLeft || 0
    e.preventDefault()
  }

  const handleMouseMove = (e: MouseEvent) => {
    if (!isDragging.value) return
    const deltaX = e.clientX - startX.value
    if (containerRef.value) {
      containerRef.value.scrollLeft = startScrollLeft.value - deltaX
    }
  }

  const handleMouseUp = () => {
    isDragging.value = false
  }

  const enable = () => {
    if (stopListeners.value.length > 0) return

    const container = containerRef.value
    if (!container) return
    container.style.userSelect = 'none'

    stopListeners.value = [
      useEventListener(container, 'mousedown', handleMouseDown, { passive: false }),
      useEventListener(document, 'mousemove', handleMouseMove, { passive: false }),
      useEventListener(document, 'mouseup', handleMouseUp, { passive: false }),
    ]
  }

  const disable = () => {
    if (stopListeners.value.length === 0) return

    if (containerRef.value) {
      containerRef.value.style.userSelect = 'auto'
    }
    stopListeners.value.forEach((stop) => stop())
    stopListeners.value = []
  }

  onUnmounted(disable)

  return { enable, disable }
}
